# -*- coding: utf8 -*-
import random
from magic import Magic
from skill import Skill
#from Statement import State,EnableState,UnableState,OperableState
class Human(object):
    '''人类变身为战士'''
    def __init__(self,mhp,hp,mp=0,mov=2,atk=10,defend=5,
                    exp=0,int=0,money=1000,name=None,side = "hero"):
        self.mhp=mhp   # 最大HP
        self.hp=hp
        self.mp=mp
        self.mov=mov   # your move
        self.atk=atk  # your atk
        self.defend=defend    # your defend
        self.int=int
        self.atk_add = 0  # your bangkill
        self.exp = exp # 人物经验
        self.name = name
        #self.mround = 0 # 各种行为消耗值
        self.position=(0,0)
        self.money = money #初始金钱
        self.mybag = [] #和背包连接
        self.myEquip = {}  #已装备的物品
        self.newAtk=self.atk
        self.newDefend=self.defend
        self.side = side
        self.state= "Unable"
        self.learned_magics = []
        self.defend_magics = [] #正在使用中的被动魔法
    def useItem(self,item):
        if self.mround>=0:
            self.hp += item.hp
            self.atk += item.atk
            self.mov += item.mov
            self.defend += item.defend
            self.mround = self.mround - 3 #计算行为值
            if self.hp>self.mhp:self.hp=self.mhp

    def learn(self, magic):
        if not isinstance(magic, Magic):
            return False
        if magic in self.learned_magics:
            return False
        if self.heroLV < magic.required_level:
            return False
        if self.isOver():
            return False
        
        self.learned_magics.append(magic)  
        return True
        
	
    def getLevel(self):
        '''获取人物等级'''
        return self.exp/100+1
    heroLV = property(getLevel)
    def equip(self,equipment):
        if equipment.owner == None and self.heroLV>=equipment.lv:
            self.myEquip[id(equipment)] = equipment
            self.newAtk += equipment.atk
            self.newDefend += equipment.defend
            equipment.owner = self
            return True
        return False
    def equipBag(self,bag):
        if bag.owner == None:
            bag.owner = self
            self.mybag = bag
            return True
        return False
    def leftEquip(self,equipment):
        if id(equipment) in self.myEquip:
            self.newAtk -= equipment.atk
            self.newDefend -= equipment.defend
            equipment.owner = None
            self.mybag.append(equipment)
            del self.myEquip[id(equipment)]
            return True
        return False
    def useItem(self,item):
        if self.state== "Enable" or self.state=="Operable":
            self.hp += item.hp
            self.atk += item.atk
            self.mov += item.mov
            self.defend += item.defend
            self.state = "Unable"
            if self.hp>self.mhp:self.hp=self.mhp
            del item
    def atkRound(self,target,distance=1):
        a,b=self.position
        c,d=target.position
        if abs(a-c)+abs(b-d)<=distance:
            return True
        return False
    def attack(self,target,bang=5):
        '''计算产生何种攻击方式'''
        if self.atkRound(target) and self.state=="Enable" or self.state=="Operable":
        # if 1:
            roll=random.randint(1,1000)
            if bang==1:
                self.atk_add = int(self.newAtk*0.5)
                return self.realAttack(target)   
            elif bang==0:
                self.atk_add = 0
                return self.realAttack(target)
            elif roll>51 and bang==5:
                self.atk_add = 0
                return self.realAttack(target)
            elif roll<=51 and bang==5:
                self.atk_add = int(self.newAtk*0.5)
                return self.realAttack(target)       
        return False
    def realAttack(self,target):
        '''根据公式真实攻击'''
        damage=self.newAtk+self.atk_add-target.defend
        target.hp=target.hp-damage
        for m in target.defend_magics:
            m.attacked(target)
        target.defend_magics = []
        skill = Skill(self,target) # 经验模块
        self.state="Unable"
        if self.atk_add==0:
            return target.hp,False
        return target.hp,True
    def magicAttack(self,target):
        damage=self.int-target.defend
        target.hp=target.hp-damage
        skill=Skill(self,target)
        self.state="Unable"
    def isOver(self):
        '''判断自己是否已经死亡'''
        print 'HP:' ,self.hp
        if self.hp<=0:
            print 'you dead'
            return True
        return False
class Seller(type):
    '''商人的元类'''
    def __new__(cls,classname,bases,classdict):
        def checkLegal(self,ppl,x):
            if ppl.money > x.price:  #需求追加武器/道具的价格属性
                if ppl.mybag.baglimited():
                    return True
                print 'your bag is FULL !'
            print 'you need more money'
            return False
        def buy(self,ppl,x):
            if checkLegal():
                ppl.mybag.addItem(x)
                ppl.money = ppl.money - x.price
                return True
            return False
        def sell(self,ppl,x):
            if ppl.mybag.baglimited():
                ppl.money = ppl.money + (x.price)/2
                del x
        newdict={"checkLegal":checkLegal,"buy":buy,"sell":sell}
        newdict.update(classdict)
        return type.__new__(cls,classname,bases,newdict)
class Mage(type):
    '''冰火法师的元类'''
    def __new__(cls,classname,bases,classdict):
        def __init__(self,mhp,hp,mov=2,atk=5,int=15,defend=5, #新添加默认的法术攻击力
                     mdefend=10,exp=0,money=1000,name='Mage'):    #削弱法师的物理攻击力
            self.mhp=mhp
            self.hp=hp
            self.mov=mov
            self.atk=atk    #保持atk属性不变，为物理攻击
            self.int=int  #新增加int为法系攻击力，为以后法术调用做准备
            self.defend=defend
            self.atk_add=0
            self.exp=exp
            self.name=name
            self.mround=0
            self.position=(0,0)
            self.money=money
            self.mybag=[]
            self.myEquip={}
            self.newAtk=self.atk
            self.newDefend=self.defend
        def fireBall(self,target):
            if self.atkRound(target,distance=2) and self.state=="Enable" or self.state=="Operable":
                self.magicAttack(target)
class Warrior(type):
    '''战士'''
    def __new__(cls,classname,bases,classdict):
        def comboAttack(self,target):
            if self.atkRound(target) and self.state=="Enable" or self.state=="Operable":
                for i in range(0,2):	
                    roll=random.randint(1,1000)
                    if roll>51:
                        self.atk_add = 0
                        self.realAttack(target)
                    elif roll<=51:
                        self.atk_add = int(self.newAtk*0.5)
                        self.realAttack(target)
                return True
            return False
        newdict={"comboAttack":comboAttack}
        newdict.update(classdict)
        return type.__new__(cls,classname,bases,newdict)
        
class Priest(type):
    '''牧师'''
    def __new__ (cls,classname,bases,classdict):
        def fastTreatment (self,target):
            if self.atkRound(target,distance=2) and self.state=="Enable" or self.state=="Operable":
                target.hp += int(target.mhp/2)
                self.state="Unable"
                if target.hp>target.mhp:target.hp=target.mhp
                return True
            return False
        def powerTreatment (self,target):
            if self.atkRound(target) and self.state=="Enable" or self.state=="Operable":
                target.hp = target.mhp
                self.state="Unable"
                return True
            return False
        def farTreatment (self,target):
            if self.atkRound(target,distance=10) and self.state=="Enable" or self.state=="Operable":
                target.hp += int(target.mhp/4)
                self.state="Unable"
                if target.hp>target.mhp:target.hp=target.mhp
                return True
            return False  
        newdict={"fastTreatment":fastTreatment,"powerTreatment":powerTreatment,"farTreatment":farTreatment}
        newdict.update(classdict)
        return type.__new__(cls,classname,bases,newdict)
        
class Hunter(type):
    def __new__(cls,classname,bases,classdict):
        def shoot (self,target):   #射击攻击 ，攻击距离2
            if self.atkRound(target,distance=2) and self.state=="Enable" or self.state=="Operable":
                roll=random.randint(1,1000)
                if roll>51:
                    self.atk_add = 0
                    self.realAttack(target)
                elif roll<=51:
                    self.atk_add = int(self.newAtk*0.5)
                    self.realAttack(target)
                return True
            return False
        def farShoot (self,target):  #远距离射击，攻击范围8，命中率40%
            if self.atkRound(target,distance=6) and self.state=="Enable" or self.state=="Operable":
                roll=random.randint(1,100)
                if roll>40:
                    self.atk_add = 0
                    self.realAttack(target)
                elif roll<=40:
		    self.state = "Unable"
                return True
            return False
        newdict={"shoot":shoot,"farShoot":farShoot}
        newdict.update(classdict)
        return type.__new__(cls,classname,bases,newdict)
                         
class Factory(object):
    @staticmethod
    def new(career,**args):
        return career(str(career),(Human,),{})(**args)
    #def newtype(cls,career,*args):
    #    return career(str(career),(type,),{})
    	
class Player(Human):
    '''默认的人类出生为战士'''
    __metaclass__= Warrior
    
    def use_magic(self, magic, target=None):
        if not magic in self.learned_magics:
            print 'You should learn first'
            return False
        if not magic.accurate:
            import random
            if random.randint(0,10) > 5:
                return False
            
        if not self.isOver() and self.mp >= magic.mp_cost:
            self.mp -= magic.mp_cost
            
            if target:
                magic.cast(target)
            else:
                magic.cast(self)
        
            return True
            
class Enemy(Human):
    __metaclass__= Warrior
